﻿using UnityEngine;
using UnityEditor;
using System.IO;
using System.Collections.Generic;
/// <summary>
/// 查找Assets中的引用
/// </summary>
public class FindReferencesInAssets : EditorWindow
{
    public static string filePath = Application.dataPath + "/Resources/FindReferencesConfiguration/FindReferencesInFolderPath";
    public static List<Object> allObjectList = new List<Object>();
    private static int startIndex;
    private static string[] files;
    private static List<string> matchList;
    private static string path;
    private static int instanceId;

    [MenuItem("Assets/FindReferencesInAssets &Q")]
    public static void Find()
    {
        allObjectList.Clear();
        instanceId = Selection.activeObject.GetInstanceID();
        path = AssetDatabase.GetAssetPath(Selection.activeObject);
        #region 匹配当前Assets下指定的文件
        files = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories);
        matchList = new List<string>();
        for (int i = 0; i < files.Length; i++)
        {
            if (files[i].Contains("TilePrefabs") || files[i].Contains("objectTile"))
            {
                continue;
            }
            if (files[i].EndsWith(".prefab") 
                || files[i].EndsWith(".unity")
                || files[i].EndsWith(".mat")
                || files[i].EndsWith(".asset")
                || files[i].EndsWith(".anim")
                || files[i].EndsWith(".controller")
                )
            {
                matchList.Add(files[i]);
            }
        }
        Debug.LogFormat("寻找{0}引用:", Selection.activeObject.name);
        EditorApplication.update += Event_FindReferences;
        #endregion
    }

    [MenuItem("Assets/FindVFXReferencesInAssets %E")]
    public static void FindVFXReference()
    {
        instanceId = Selection.activeObject.GetInstanceID();
        path = AssetDatabase.GetAssetPath(Selection.activeObject);
        #region 匹配当前Assets下指定的文件
        matchList = new List<string>();
        files = Directory.GetFiles(Application.dataPath + "/Resources/Prefabs/VFX", "*.*", SearchOption.AllDirectories);
        for (int i = 0; i < files.Length; i++)
        {
            if (files[i].EndsWith(".prefab")
                || files[i].EndsWith(".unity")
                || files[i].EndsWith(".mat")
                || files[i].EndsWith(".asset")
                || files[i].EndsWith(".anim")
                || files[i].EndsWith(".controller")
                )
            {
                matchList.Add(files[i]);
            }
        }
        files = Directory.GetFiles(Application.dataPath + "/ResourcesRaw/VFX", "*.*", SearchOption.AllDirectories);
        for (int i = 0; i < files.Length; i++)
        {
            if (files[i].EndsWith(".prefab")
                || files[i].EndsWith(".unity")
                || files[i].EndsWith(".mat")
                || files[i].EndsWith(".asset")
                || files[i].EndsWith(".anim")
                || files[i].EndsWith(".controller")
                )
            {
                matchList.Add(files[i]);
            }
        }
        Debug.LogFormat("寻找{0}引用:", Selection.activeObject.name);
        EditorApplication.update += Event_FindReferences;
        #endregion
    }

    static void Event_FindReferences()
    {

        string findPath = GetRelativeAssetsPath(matchList[startIndex]);
        bool isCancel = EditorUtility.DisplayCancelableProgressBar("匹配资源中", findPath, (float)startIndex / (float)files.Length);
        Object targetObject = AssetDatabase.LoadAssetAtPath<Object>(findPath);
        //移除自身的路径
        //Debug.Log(findPath);
        if (findPath != path)
        {
            Object[] roots = new Object[] { targetObject };
            Object[] objs = EditorUtility.CollectDependencies(roots);
            foreach (Object obj in objs)
            {
                //如果他们的引用ID相等那么记录他们
                if (obj != null)
                {
                    if (obj.GetInstanceID() == instanceId)
                    {
                        //Debug.Log("<color=green>"+findPath+"</color>");
                        //?这个打不出来
                        UnityEngine.Debug.Log("<color=green>" + findPath + "</color>", AssetDatabase.LoadAssetAtPath<Object>(findPath));
                        allObjectList.Add(AssetDatabase.LoadAssetAtPath<Object>(findPath));
                    }
                }
            }
        }

        startIndex++;
        if (isCancel || startIndex >= matchList.Count)
        {
            EditorUtility.ClearProgressBar();
            startIndex = 0;
            Debug.Log("匹配结束");
            Object[] toSelection = new Object[allObjectList.Count];
            for (int i = 0; i < allObjectList.Count; i++)
            {
                toSelection[i] = allObjectList[i];
            }
            Selection.objects = toSelection;
            EditorApplication.update -= Event_FindReferences;
        }
    }

    static private string GetRelativeAssetsPath(string path)
    {
        return "Assets" + Path.GetFullPath(path).Replace(Path.GetFullPath(Application.dataPath), "").Replace('\\', '/');
    }

    [MenuItem("Assets/FindReferencesChangePathWidow")]   //CONTEXT（大写） 组件名  按钮名
    static void OpenChangePathWindow(MenuCommand cmd)
    {

        FileInfo file = new FileInfo(filePath);
        string jsonData = "";
        if (file.Exists)
        {
            StreamReader reader = new StreamReader(filePath);
            jsonData = reader.ReadToEnd();
            reader.Close();
            reader.Dispose();
            FindReferencesChangePathWidow.bothData = SimpleJson.SimpleJson.DeserializeObject<FindReferencesPath>(jsonData);
        }
        else
        {
            FindReferencesChangePathWidow.bothData = new FindReferencesPath();
        }
        EditorWindow.GetWindow(typeof(FindReferencesChangePathWidow));
    }

}

public class FindReferencesChangePathWidow : EditorWindow
{
    public static FindReferencesPath bothData;
    public static List<Object> allObjectList = new List<Object>();
    private static int startIndex = 0;
    private static string[] files;
    private static List<string> matchList;
    private static int instanceId;
    private static string path;
    void OnGUI()
    {
        GUILayout.Label("添加要查找的文件夹，在你开始寻找引用时，选取这些文件夹检测", GUILayout.MaxWidth(300));
        if (GUILayout.Button("删除全部"))
        {
            bothData.path.Clear();
            bothData.choicePath = "";
        }
        if (bothData.path == null)
        {
            bothData.path = new List<DataResPath>();
        }
        for (int i = 0; i < bothData.path.Count; i++)
        {
            DrawWindow(bothData.path[i]);
        }
        GUILayout.BeginHorizontal();
        {
            bothData.choicePath = EditorGUILayout.TextField(bothData.choicePath);
        }
        GUILayout.EndHorizontal();
        if (GUILayout.Button("添加"))
        {
            bothData.choicePath.Replace(" ", "");
            for (int i = 0; i < bothData.path.Count; i++)
            {
                if (bothData.path[i].path == bothData.choicePath)
                {
                    ShowNotification(new GUIContent("文件夹重复添加"));
                    return;
                }
            }
            if(Directory.Exists(Application.dataPath + "/" + bothData.choicePath))
            {
                DataResPath dataResPath = new DataResPath();
                dataResPath.path = bothData.choicePath;
                dataResPath.flag = true;
                dataResPath.fullpath = Application.dataPath + "/" + dataResPath.path;
                bothData.path.Add(dataResPath);
                SaveConfiguration();
            }
            else
            {
                ShowNotification(new GUIContent("Asset下不存在此文件夹路径"));
                return;
            }
        }
        if (GUILayout.Button("寻找指定路径引用"))
        {
            SaveConfiguration();
            Find();
        }
    }
    void DrawWindow(DataResPath _Data, float offset = 0)
    {
        GUILayout.BeginHorizontal();
        GUILayout.Label("", GUILayout.MaxWidth(offset + 5));
        _Data.flag = EditorGUILayout.Toggle(_Data.path, _Data.flag);
        if (GUILayout.Button("删除"))
        {
           for(int i=0;i< bothData.path.Count;i++)
            {
                if(bothData.path.Contains(_Data))
                {
                    bothData.path.Remove(_Data);
                }
            }
            SaveConfiguration();
        }
        GUILayout.EndHorizontal();
    }

    static List<string> bothFindFile = new List<string>();
    public static void Find()
    {
        instanceId = Selection.activeObject.GetInstanceID();
        path = AssetDatabase.GetAssetPath(Selection.activeObject);
        bothFindFile = new List<string>();
        #region 匹配当前Assets下指定的文件
        for (int i = 0; i < bothData.path.Count; i++)
        {
            FindPathString(bothData.path[i]);
        }

        matchList = new List<string>();

        for (int i = 0; i < bothFindFile.Count; i++)
        {
            Debug.Log(bothFindFile[i]);
            files = Directory.GetFiles(bothFindFile[i], "*.*", SearchOption.TopDirectoryOnly);
            for (int j = 0; j < files.Length; j++)
            {
                if (files[j].EndsWith(".prefab")
                    || files[j].EndsWith(".unity")
                    || files[j].EndsWith(".mat")
                    || files[j].EndsWith(".asset")
                    || files[j].EndsWith(".anim")
                    || files[j].EndsWith(".controller")
                    )
                {
                    matchList.Add(files[j]);
                }
            }
        }

        if (matchList.Count > 0)
        {
            Debug.LogFormat("寻找{0}引用:", Selection.activeObject.name);
            EditorApplication.update += Event_FindReferences;
        }
        else
        {
            Debug.LogFormat("为选择文件夹");
        }
        #endregion
    }

    static void FindPathString(DataResPath data)
    {
        if (data.flag)
        {
            bothFindFile.Add(data.fullpath);
        }

    }

    static void Event_FindReferences()
    {
        string findPath = GetRelativeAssetsPath(matchList[startIndex]);
        bool isCancel = EditorUtility.DisplayCancelableProgressBar("匹配资源中", findPath, (float)startIndex / (float)files.Length);
        Object targetObject = AssetDatabase.LoadAssetAtPath<Object>(findPath);
        //移除自身的路径
        //Debug.Log(findPath);
        if (findPath != path)
        {
            Object[] roots = new Object[] { targetObject };
            Object[] objs = EditorUtility.CollectDependencies(roots);
            foreach (Object obj in objs)
            {
                //如果他们的引用ID相等那么记录他们
                if (obj != null)
                {
                    if (obj.GetInstanceID() == instanceId)
                    {
                        //Debug.Log("<color=green>"+findPath+"</color>");
                        //?这个打不出来
                        UnityEngine.Debug.Log("<color=green>" + findPath + "</color>", AssetDatabase.LoadAssetAtPath<Object>(findPath));
                        allObjectList.Add(AssetDatabase.LoadAssetAtPath<Object>(findPath));
                    }
                }
            }
        }

        startIndex++;
        if (isCancel || startIndex >= matchList.Count)
        {
            EditorUtility.ClearProgressBar();
            startIndex = 0;
            Debug.Log("匹配结束");
            Object[] toSelection = new Object[allObjectList.Count];
            for (int i = 0; i < allObjectList.Count; i++)
            {
                toSelection[i] = allObjectList[i];
            }
            Selection.objects = toSelection;
            EditorApplication.update -= Event_FindReferences;
        }
    }

    private static void SaveConfiguration()
    {
        string activityDataString = SimpleJson.SimpleJson.SerializeObject(bothData);
        FileInfo file = new FileInfo(FindReferencesInAssets.filePath);
        StreamWriter writer = file.CreateText();   //用文本写入的方式
        writer.Write(activityDataString);   //写入数据
        writer.Close();   //关闭写指针
        writer.Dispose();    //销毁写指针
    }

    static private string GetRelativeAssetsPath(string path)
    {
        return "Assets" + Path.GetFullPath(path).Replace(Path.GetFullPath(Application.dataPath), "").Replace('\\', '/');
    }
}
public class FindReferencesPath
{
    public string choicePath = "";
    public List<DataResPath> path;
}
